package com.hollycrm.unicom.sheet.flowsupport;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.transaction.UserTransaction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hollycrm.springframework.factory.DefaultBeanFactory;
import com.hollycrm.unicom.logsupport.LogManager;
import com.hollycrm.unicom.logsupport.OperationLog;
import com.hollycrm.unicom.security.AuthToken;
import com.hollycrm.unicom.sheet.Constants;
import com.hollycrm.unicom.sheet.SheetException;
import com.hollycrm.unicom.sheet.flow.SheetAction;
import com.hollycrm.unicom.sheet.BeanResource;
import com.hollycrm.unicom.sheet.domain.MainSheet;
import com.hollycrm.unicom.usersupport.Department;

/**
 * FlowSupportManagerProxyBean
 *
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author Tian Kai
 * @version 1.0
 */
public class FlowSupportManagerProxyBean implements FlowSupportManager {

    private Log logger = LogFactory.getLog(getClass());
    private UserTransaction userTransaction;
    private FlowSupportManager target;

    /**
     * getDeptAcceptCategoryList
     *
     * @param flowID String
     * @param deptID String
     * @param operateType String
     * @return List
     */
    public List getDeptAcceptCategoryList(String flowID, String deptID,
                                          String operateType) {
        return target.getDeptAcceptCategoryList(flowID, deptID, operateType);
    }

    /**
     * getDeptReceiveCategoryList
     *
     * @param flowID String
     * @param deptID String
     * @param operateType String
     * @return List
     */
    public List getDeptReceiveCategoryList(String flowID, String deptID,
                                           String operateType) {
        return target.getDeptReceiveCategoryList(flowID, deptID, operateType);
    }

    /**
     * getPostDeptList
     *
     * @param flowID String
     * @param deptID String
     * @param operateType String
     * @return List
     */
    public List getPostDeptList(String flowID, String deptID,
                                String operateType) {
        return target.getPostDeptList(flowID, deptID, operateType);
    }

    /**
     * getNextDeptID
     *
     * @param flowID String
     * @param deptID String
     * @param operateType String
     * @return String
     */
    public String getNextDeptID(String flowID, String deptID,
                                String operateType) {
        return target.getNextDeptID(flowID, deptID, operateType);
    }

    /**
     * getFuncOperationList
     *
     * @param flowID String
     * @param deptID String
     * @param funcType String
     * @param statusType String
     * @return List
     */
    public List getFuncOperationList(String flowID, String deptID,
                                     String funcType, String statusType) {
        return target.getFuncOperationList(flowID, deptID, funcType, statusType);
    }

    /**
     * getProcessActionList
     *
     * @param flowID String
     * @param deptID String
     * @param operateType String
     * @return List
     */
    public List getProcessActionList(String flowID, String deptID,
                                     String operateType) {
        return target.getProcessActionList(flowID, deptID, operateType);
    }

    /**
     * getDeptChildrenAsMove
     *
     * @param deptID String
     * @return List
     */
    public List getDeptChildrenAsMove(String deptID) {
        return target.getDeptChildrenAsMove(deptID);
    }

    /**
     * getDeptChildrenAsMove
     * @param deptID String
     * @param isAll boolean
     * @return List
     * @since 2005-04-19
     */
    public List /*SheetMove*/ getDeptChildrenAsMove(String deptID, boolean isAll){
       return target.getDeptChildrenAsMove(deptID,isAll);
    }


    /**
     * doOperate
     *
     * @param authToken AuthToken
     * @param flowID String
     * @param deptID String
     * @param operateType String
     * @param doCtx DoOperateContext
     * @return DoOperateContext
     */
    public DoOperateContext doOperate(AuthToken authToken, String flowID, String deptID,
                                      String operateType,
                                      DoOperateContext doCtx) {
        boolean success = false;
        try {
            doCtx.addOutputAttr("startTime",
                                ( (SimpleDateFormat)
                                 DefaultBeanFactory.getBean(BeanResource.SDF_Y2S)).
                                format(new Date()));
            List actions = getProcessActionList(flowID, deptID, operateType);

            userTransaction.begin();
            for (Iterator iter = actions.iterator(); iter.hasNext(); ) {
                SheetAction action = (SheetAction) iter.next();
                String beanID = action.getActionClass();
                ( (ActionExecuteLogic) DefaultBeanFactory.getBean(beanID)).
                    execute(authToken, action, doCtx);
                if (action.getReturnKey() != null &&
                    action.getReturnKey().trim().length() != 0)
                    doCtx.addOutputAttr(Constants.SHEET_ACTION_RETURN_KEY,
                                        action.getReturnKey());
            }
            userTransaction.commit();
            success = true;
        }
        catch (Exception ex) {
            logger.error("[e] " + ex.getMessage(), ex);
            try {
                userTransaction.rollback();
            }
            catch (Exception ex1) {
                logger.error("[e] " + ex1.getMessage());
            }
            throw new SheetException("operate.failure." + operateType);
        }

        writeLog(authToken, doCtx, operateType, success);
        doCtx.addOutputAttr("operateType", operateType);
        postProcessTemplateMethod(authToken, doCtx);

        return doCtx;
    }

    private void postProcessTemplateMethod(AuthToken authToken,
                                           DoOperateContext doCtx) {
        ( (PostExecuteManagerBean) DefaultBeanFactory.getBean(BeanResource.
            POSTEXECUTE_MANAGER)).postExecute(authToken, doCtx);
    }

    private void writeLog(AuthToken authToken, DoOperateContext doCtx,
                          String operateType, boolean success) {
        try {
            OperationLog log = new OperationLog();
            log.setOperationType(operateType);
            log.setOperator(authToken.getUserCode());
            log.setServiceType(Constants.SHEET_SERVICE_TYPE);
            log.setObjectType(Constants.OBJECT_TYPE);
            log.setStartTime( (String) doCtx.getOutputAttr("startTime"));
            log.setComputerIP( (String) authToken.getAttribute("clientIP"));
            log.setEndFlag(success ? Constants.TRUE : Constants.FALSE);
            log.setEndTime( ( (SimpleDateFormat) DefaultBeanFactory.getBean(BeanResource.SDF_Y2S)).format(new Date()));
            log.setMemo( (String) doCtx.getOutputAttr("memo"));

            //modified since 2005-03-29
            if(doCtx.getInputAttr("sheetFlowNO")!=null)
                log.setOperationObject((String)doCtx.getInputAttr("sheetFlowNO"));

            MainSheet mainSheet = (MainSheet) doCtx.getOutputAttr(MainSheet.class);
            if (mainSheet != null) {
                log.setAcceptCallID(mainSheet.getLastAcceptRecord().
                                    getAcceptCallID());
                log.setAcceptType(mainSheet.getLastAcceptRecord().getAccessType());
                log.setAnswerType(mainSheet.getLastAcceptRecord().getAnswerType());
                log.setBusinessType(mainSheet.getBusinessType());
                log.setCustomerLevel(mainSheet.getCustomerInfo().
                                     getCustomerLevel());
                log.setCustomerType(mainSheet.getCustomerInfo().getCustomerType());
                log.setOperationObject(mainSheet.getSheetFlowNO());
            }
            log.checkNull();

            ( (LogManager) DefaultBeanFactory.getBean("operationLogManager")).
                writeLog(log);
        }
        catch (Exception ex) {
            logger.warn("[w] write operate log failure: " + ex.getMessage(), ex);
        }
    }

    public FlowSupportManager getTarget() {
        return target;
    }
    public void setTarget(FlowSupportManager target) {
        this.target = target;
    }
    public UserTransaction getUserTransaction() {
        return userTransaction;
    }
    public void setUserTransaction(UserTransaction userTransaction) {
        this.userTransaction = userTransaction;
    }

    public List getLeafDeptAsMove(String deptID, String flowID) {
        return target.getLeafDeptAsMove(deptID,flowID);
    }

    public Department retrieveDepartment(String deptID) {
        return target.retrieveDepartment(deptID);
    }

}
